package com.wdd.myplatform.utils;

import com.wdd.myplatform.config.MinioConfig;
import io.minio.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;

@Component
public class MinioUtil {
    /**
     * 桶名称
     */
    @Value("${minio.bucketName}")
    private String bucketName;

    @Autowired
    private MinioConfig minioConfig;

    @Autowired
    private MinioClient minioClient;

    /**
     * description: 判断bucket是否存在，不存在则创建
     *
     */
    public void createBucket(String name) {
        try {
            boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(name).build());
            if (!exists) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(name).build());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * description: 判断bucket是否存在，不存在则创建公共桶，对外可读可写
     *
     */
    public void createPublicBucket(String bucketName) {
        try {
            boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!exists) {
                StringBuffer stringBuffer = new StringBuffer();
                stringBuffer.append("{\n" +
                        "    \"Version\": \"2012-10-17\",\n" +
                        "    \"Statement\": [\n" +
                        "        {\n" +
                        "            \"Effect\": \"Allow\",\n" +
                        "            \"Action\": [\n" +
                        "                \"s3:*\"\n" +
                        "            ],\n" +
                        "\t\t\t\"Principal\": \"*\",\n" +
                        "            \"Resource\": [\n" +
                        "                \"arn:aws:s3:::distribute-bucket1*\"\n" +
                        "            ]\n" +
                        "        }\n" +
                        "    ]\n" +
                        "}");
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
                minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(stringBuffer.toString()).build());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * description: 上传文件
     *
     * @param file
     */
    public String upload(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        String[] split = fileName.split("\\.");
        if (split.length > 1) {
            fileName = split[0] + "_" + System.currentTimeMillis() + "." + split[1];
        } else {
            fileName = fileName + System.currentTimeMillis();
        }
        InputStream in = null;
        try {
            in = file.getInputStream();
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .stream(in, in.available(), -1)
                    .contentType(file.getContentType())
                    .build()
            );
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return minioConfig.getEndpoint()+"/"+bucketName+"/"+ fileName;
    }

    /**
     * description: 上传文件
     *
     * @param file
     */
    public String upload(MultipartFile file, String bucketName) {
        String fileName = file.getOriginalFilename();
        String[] split = fileName.split("\\.");
        if (split.length > 1) {
            fileName = split[0] + "_" + System.currentTimeMillis() + "." + split[1];
        } else {
            fileName = fileName + System.currentTimeMillis();
        }
        InputStream in = null;
        try {
            in = file.getInputStream();
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .stream(in, in.available(), -1)
                    .contentType(file.getContentType())
                    .build()
            );
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return minioConfig.getEndpoint()+"/"+bucketName+"/"+ fileName;
    }

    /**
     * description: 从本地上传文件
     *
     * @param filePath 文件路径+名称
     */
    public String upload(String filePath) {
        File file= new File(filePath);
        String fileName = file.getName();
        String[] split = fileName.split("\\.");
        if (split.length > 1) {
            fileName = split[0] + "_" + System.currentTimeMillis() + "." + split[1];
        } else {
            fileName = fileName + System.currentTimeMillis();
        }
        InputStream in = null;
        try {
            in = FileUtils.openInputStream(file);
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .stream(in, in.available(), -1)
//                    .contentType(file.getContentType())
                    .build()
            );
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return minioConfig.getEndpoint()+"/"+bucketName+"/"+ fileName;
    }

    /**
     * description: 从本地上传文件
     *
     * @param filePath 文件路径+名称
     */
    public String upload(String filePath,String bucketName) {
        File file= new File(filePath);
        String fileName = file.getName();
        String[] split = fileName.split("\\.");
        if (split.length > 1) {
            fileName = split[0] + "_" + System.currentTimeMillis() + "." + split[1];
        } else {
            fileName = fileName + System.currentTimeMillis();
        }
        InputStream in = null;
        try {
            in = FileUtils.openInputStream(file);
            minioClient.putObject(PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .stream(in, in.available(), -1)
//                    .contentType(file.getContentType())
                            .build()
            );
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return minioConfig.getEndpoint()+"/"+bucketName+"/"+ fileName;
    }

    /**
     * description: 浏览器下载文件
     *@param filePath    //文件url
     *@param fileName    //下载文件的名称，不填则默认为原始文件名称
     */
    public void download(HttpServletResponse response, String filePath, String fileName) {
        if(StringUtils.isBlank(fileName)){
            fileName = StringUtils.substringAfterLast(filePath,"/");
        }
        InputStream in = null;
        ByteArrayOutputStream out = null;
        URL url = null;
        try {
            url = new URL(filePath);
            in = new DataInputStream(url.openStream());
            out = new ByteArrayOutputStream();
            IOUtils.copy(in, out);
            //封装返回值
            byte[] data = out.toByteArray();
            response.reset();
            response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
            response.addHeader("Content-Length", "" + data.length);
            response.setContentType("application/octet-stream;charset=UTF-8");
            OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
            outputStream.write(data);
            outputStream.flush();
            outputStream.close();
            response.flushBuffer();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(out);
        }
    }

    /**
     * 下载文件到本地
     * @param fileName minio文件名
     * @param diskFileName 下载到磁盘的文件路径及名称
     */
    public void downloadFile2Disk(String fileName,String diskFileName){
        InputStream in = null;
        try {
            in = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
            FileUtils.copyInputStreamToFile(in, new File(diskFileName));
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            IOUtils.closeQuietly(in);
        }
    }

    /**
     * 下载文件到本地
     * @param fileName minio文件名
     * @param bucketName 桶名称
     * @param diskFileName 下载到磁盘的文件路径及名称
     */
    public void downloadFile2Disk(String fileName,String bucketName,String diskFileName){
        InputStream in = null;
        try {
            in = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
            FileUtils.copyInputStreamToFile(in, new File(diskFileName));
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            IOUtils.closeQuietly(in);
        }
    }

    /**
     * 删除bucket
     * @param bucketName
     */
    public void removeBucket(String bucketName){
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除对象
     * @param bucketName
     * @param fileName
     */
    public void removeObject(String bucketName,String fileName){
        try {
            minioClient.removeObject(RemoveObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    //.versionId("my-versionid") //还可以删除指定版本号的对象
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String queryBucketPolicy(String bucketName) {
        String bucketPolicy = null;
        try {
            bucketPolicy = minioClient.getBucketPolicy(GetBucketPolicyArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bucketPolicy;
    }

}
